package cn.com.transfer.services;

import cn.com.transfer.params.IcbcParams;
import cn.com.transfer.utils.Constants;
import cn.com.transfer.utils.IcbcInfo;
import cn.com.transfer.utils.IcbcNative;
import flexjson.JSONDeserializer;
import flexjson.JSONSerializer;
import org.apache.commons.lang.StringUtils;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.Record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.lang.model.element.VariableElement;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * 对账(对账时间在签到时间之外，不能做冲正交易)
 * banlance 0-未对账 1-已对账
 * reverse 0无冲正 1-成功 2-失败
 * balanceMsg 对账错误信息
 */
public class AccCheck extends MsgHandlerService {
    private Logger logger = LoggerFactory.getLogger(AccCheck.class);

    @Override
    public String handler(Map params) {
        Map rtn = new HashMap();
        String period = (String) params.get("period");
        try {
            Calendar ca = Calendar.getInstance();
            IcbcParams req = new IcbcParams(3);
            req.schoolCode = IcbcInfo.schoolId;
            req.transCode = Constants.ICBC_TRANS_SIGN_BALANCE;
            req.transTime = String.format("%02d:%02d:%02d", ca.get(Calendar.HOUR_OF_DAY), ca.get(Calendar.MINUTE), ca.get(Calendar.SECOND));
            req.transDate = String.format("%04d-%02d-%02d", ca.get(Calendar.YEAR), ca.get(Calendar.MONTH) + 1, ca.get(Calendar.DAY_OF_MONTH));

            if (StringUtils.isBlank(period) || !period.matches("(20\\d{2})(1[0-2]|0\\d)(3[01]|[0-2]\\d)")) {
                ca.add(Calendar.DAY_OF_MONTH, -1);
                period = String.format("%04d%02d%02d", ca.get(Calendar.YEAR), ca.get(Calendar.MONTH) + 1, ca.get(Calendar.DAY_OF_MONTH));
            }
            req.accDate = String.format("%s-%s-%s", period.substring(0, 4), period.substring(4, 6), period.substring(6, 8));
            req.mac = req.genMac(0);
            IcbcParams resp = sendMessage(req);
            checkNotNull(resp, "连接服务器失败");
            checkArgument(resp.rtnCode.equals("00000"), Constants.msgMap.get(resp.rtnCode) == null ? resp.rtnMsg : Constants.msgMap.get(resp.rtnCode));

            String count = IcbcNative.decrypt(resp.transCount, 0).trim();
            logger.info("正交易总笔数 {}, 总金额(分) {}", count, IcbcNative.decrypt(resp.moneyCount, 0).trim());
            if (Integer.valueOf(count) > 0)
                checkAcc(resp);

            rtn.put("success", true);
        } catch (Exception e) {
            logger.error("error in accCheck", e);
            rtn.put("success", false);
            rtn.put("msg", e.getMessage() != null ? e.getMessage() : e.toString());
        }

        return new JSONSerializer().serialize(rtn);
    }

    private void checkAcc(IcbcParams resp) throws Exception {
        File file = null;
        BufferedReader br = null;

        try {
            file = new File(IcbcInfo.path + File.separator + "YKT" + IcbcInfo.schoolId + resp.accDate + ".txt");
            for (int i = 0; i < 3; i++) {
                if (file.isFile()) break;
                Thread.sleep(3000);
            }
            checkArgument(file.isFile(), file.getName() + "对账文件不存在");
            br = new BufferedReader(new FileReader(file));
            String line;
            boolean first = true;
            while ((line = br.readLine()) != null) {
                if (first) {
                    first = false;
                    continue;
                }
                if (!IcbcNative.getMac(line.substring(0, line.length() - 8), 0).equals(line.substring(line.length() - 8, line.length()))) {
                    continue;
                }
                int temp = 0;
                String transTime = line.substring(temp, temp += 8).trim();
                String transDate = line.substring(temp, temp += 10).trim();
                temp += 2;      //交易类型 10 充值交易11 缴学费
                String terminalNo = line.substring(temp, temp += 10).trim();
                String transNo = line.substring(temp, temp += 12).trim();
                String bankTransNo = line.substring(temp, temp += 12).trim();
                String yktNo = line.substring(temp, temp += 16).trim();
                String bankNo = line.substring(temp, temp += 24).trim();
                String money = line.substring(temp, temp += 16).trim();

                Cnd cnd = Cnd.where("transNo", "=", transNo).and("bankTransNo", "=", bankTransNo);
                /*.and("CONVERT(varchar(100), serviceAt, 112)", "=", transDate);*/

                Record log = dao.fetch("icbcQCLog", cnd);
                if (log != null) {
                    StringBuffer err = new StringBuffer();
                    if (!log.get("terminalNo").equals(terminalNo)) err.append("errorTerminalNo,");
                    if (!log.get("bankNo").equals(bankNo)) err.append("errorBankNo,");
                    if (!log.getString("amount").equals(money)) err.append("errorMoney");
                    dao.update("icbcQCLog", Chain.make("balance", 1).add("balanceMsg", err.toString()), cnd);
                } else {
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-ddHHmmss");
                    Date serviceAt = format.parse(transDate + transTime);
                    Chain ch = Chain.make("accountNo", yktNo).add("bankNo", bankNo).add("amount", money)
                            .add("transNo", transNo).add("bankTransNo", bankTransNo).add("terminalNo", terminalNo)
                            .add("reverse", 2).add("serviceAt", serviceAt).add("balance", 1).add("accDate", resp.accDate);
                    dao.insert("icbcQCLog", ch);
                    /*ReverseTrans trans = new ReverseTrans();
                    Map map = new HashMap();
                    map.put("transNo", transNo);
                    map = new JSONDeserializer<Map>().deserialize(trans.handler(map));
                    if ((Boolean) map.get("success")) {
                        dao.update("icbcQCLog", Chain.make("reverse", 1), Cnd.where("transNo", "=", transNo).and("bankTransNo", "=", bankTransNo));
                    }*/
                }
            }
        } finally {
            try {
                br.close();
            } catch (Exception e) {
            }
        }
    }

}
